Conversation
DeepSeek's DSML protocol injects tool-call routing markers (e.g. <‖DSML‖tool_calls>, <‖DSML‖invoke ...>) into the content stream before the actual tool_calls delta arrives. These markers leak into the UI when tool calls fail or are not parsed in time. This adds _strip_dsml_markers() — a fast regex filter applied to every content chunk yielded by _parse_openai_sse(). The guard short-circuits on chunks that don't contain 'DSML' so there is zero overhead on non-DeepSeek streams. Closes lsdefine#804
|
Friendly bump — DeepSeek DSML strip is ready for review when you have a moment. Happy to tweak if needed. |
|
I tested the current PR implementation against DSML strings observed in real
_strip_dsml_markers('<||DSML||parameter name="x">abc</||DSML||parameter>')
# current result: '<abc</'
# expected: 'abc'The
chunks = ['hello<‖DS', 'ML‖tool_calls>world']
''.join(_strip_dsml_markers(x) for x in chunks)
# current result: 'hello<‖DSML‖tool_calls>world'Because each chunk is filtered independently and the fast guard requires Suggested direction: maintain a short carry-over buffer/state across SSE chunks, and match the double-pipe variants before their single-pipe substrings. Please also add regression tests for opening/closing |
Problem
DeepSeek's DSML protocol injects tool-call routing markers into the content stream before the actual
tool_callsdelta arrives. These markers (e.g.<‖DSML‖tool_calls>,<‖DSML‖invoke ...>) leak into the UI when tool calls fail or aren't parsed in time.Fix
Adds
_strip_dsml_markers()— a fast regex filter applied to every content chunk yielded by_parse_openai_sse().'DSML'‖, Unicode|, ASCII pipe|, and double-escaped formsTesting
<‖DSML‖tool_calls>,<‖DSML‖invoke name="ShellCommand" arguments="{...}">— all stripped cleanlyCloses #804